package com.atguigu.crowd.handler;

import com.atguigu.crowd.api.MySQLRemoteService;
import com.atguigu.crowd.api.RedisRemoteService;
import com.atguigu.crowd.config.ShortMessageProperties;
import com.atguigu.crowd.constant.CrowdConstant;
import com.atguigu.crowd.entity.po.MemberPO;
import com.atguigu.crowd.entity.vo.MemberLoginVO;
import com.atguigu.crowd.entity.vo.MemberVO;
import com.atguigu.crowd.util.CrowdUtil;
import com.atguigu.crowd.util.ResultEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Controller
public class MemberHandler {

    @Autowired
    ShortMessageProperties shortMessageProperties;

    @Autowired
    RedisRemoteService redisRemoteService;

    @Autowired
    MySQLRemoteService mySQLRemoteService;

    //日志
    private Logger logger = LoggerFactory.getLogger(MemberHandler.class);


    /**
     * 退出登陆
     */
    @RequestMapping("/auth/member/logout")
    public String logout(HttpSession session) {
        session.invalidate();
        return "redirect:http://localhost/auth/member/to/protal";
    }


    /**
     * 用户登陆
     */
    @RequestMapping("/auth/member/do/login")
    public String login(@RequestParam("loginacct") String loginacct, @RequestParam("userpswd") String userpswd, ModelMap modelMap, HttpSession session) {

        //1、调用远程接口根据登陆账号查询MemberPO对象
        ResultEntity<MemberPO> resultEntity = mySQLRemoteService.getMemberPOByLoginAcctRemote(loginacct);

        if (ResultEntity.FAILED.equals(resultEntity.getResult())) {
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, resultEntity.getMessage());
            return "member-login";
        }

        //获取数据库中查到的PO对象
        MemberPO memberPO = resultEntity.getData();
        logger.info("<++++++++memberPO+++++++++>"+ memberPO);
        if(memberPO == null) {
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_LOGIN_FAILED);
            return "member-login";
        }
        String userpswdDataBase = memberPO.getUserpswd();
        logger.info("<=========数据库中查出的值=========>:"+userpswdDataBase);
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        //比较数据库中密码和表单提交密码是否相等
        boolean matches = passwordEncoder.matches(userpswd, userpswdDataBase);
        if (!matches) {
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_LOGIN_FAILED);
            return "member-login";
        }

        //创建一个MemberLoginVO对象，将MemberPO中的值赋给MemberLoginVO，并将MemberLoginVO对象存入session域中
        MemberLoginVO memberLoginVO = new MemberLoginVO(memberPO.getId(), memberPO.getUsername(), memberPO.getEmail());

        session.setAttribute(CrowdConstant.ATTR_NAME_LOGIN_MEMBER, memberLoginVO);

        return "redirect:http://localhost/auth/member/to/center/page";
    }


    /**
     * 用户注册
     */
    @RequestMapping("/auth/do/member/register")
    public String register (MemberVO memberVO, ModelMap modelMap) {

        //1、获取用户输入的手机号
        String phoneNum = memberVO.getPhoneNum();
        logger.info("手机号："+phoneNum);

        //2、拼Redis中存储验证码的Key
        String key = CrowdConstant.REDIS_CODE_PREFIX + phoneNum;
        logger.info("redis的key："+key);

        //3、从Redis中读取Key对应的value
        ResultEntity<String> resultEntity = redisRemoteService.getRedisStringValueByKeyRemote(key);

        //4、检查查询操作是否有效
        String result = resultEntity.getResult();
        logger.info("从redis中查出的结果："+result);

        //如果查询失败
        if (ResultEntity.FAILED.equals(result)) {
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, resultEntity.getMessage());
            return "member-reg";
        }

        //获取redis中查出来的验证码
        String redisCode = resultEntity.getData();
        logger.info("从redis中查出来的验证码："+redisCode);

        //如果redis中查到的验证码值为null
        if (redisCode == null) {
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_CODE_NOT_EXECTS);
            return "member-reg";
        }

        //5、如果从redis能够查询到value，则比较表单验证码和redis验证码是否一致
        String formCode = memberVO.getCode();
        logger.info("表单中提交的验证码：" + formCode);

        //如果不一致
        if (!Objects.equals(formCode, redisCode)) {
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_CODE_INVALID);
            return "member-reg";
        }

        //6、如果验证码一致，则从Redis删除验证码
        ResultEntity<String> removeResultEntity = redisRemoteService.removeRedisKeyRemote(key);

        //7、执行密码加密
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String userpswdBeforeEncode = memberVO.getUserpswd();
        logger.info("未加密的密码："+userpswdBeforeEncode);
        String userpswdAfterEncode = passwordEncoder.encode(userpswdBeforeEncode);
        logger.info("加密后的密码："+userpswdBeforeEncode);
        memberVO.setUserpswd(userpswdAfterEncode);
        //8、执行保存
            //(1)创建空的MemberPO对象
            MemberPO memberPO = new MemberPO();

            //(2) 复制属性 (BeanUtils.copyProperties()是Spring中的工具类中的方法)
            //将前面参数的对象里面的数据复制到后面参数的对象里面去，没有字段就是null
            BeanUtils.copyProperties(memberVO, memberPO);
            ResultEntity<MemberPO> saveMemberResultEntity = mySQLRemoteService.saveMember(memberPO);

        if (ResultEntity.FAILED.equals(saveMemberResultEntity.getResult())) {
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, saveMemberResultEntity.getMessage());
            return "member-reg";
        }
        //使用重定向避免刷新浏览器导致重新执行注册流程
        return "redirect:http://localhost/auth/member/to/login/page";
    }


    /**
     * 在注册页面发送验证码，并存入Redis
     */
    @ResponseBody
    @RequestMapping("/auth/member/send/short/message.json")
    public ResultEntity<String> sendMessage(@RequestParam("phoneNum") String phoneNum) {

        //1、发送验证码到phoneNum手机
        ResultEntity<String> sendMessageResultEntity = CrowdUtil.sendCodeByShortMessage(
                shortMessageProperties.getHost(),
                shortMessageProperties.getPath(),
                shortMessageProperties.getMethod(),
                phoneNum,
                shortMessageProperties.getAppCode(),
                shortMessageProperties.getSign(),
                shortMessageProperties.getSkin()
        );

        //2、判断短信发送结果
        if (ResultEntity.SUCCESS == sendMessageResultEntity.getResult()) {

            //3、如果发送成功，则将验证码存入redis
            String code = sendMessageResultEntity.getData();

            //自定义验证码的key值
            String key = CrowdConstant.REDIS_CODE_PREFIX + phoneNum;
            //调用API微服务中redis模块的接口，将验证码缓存至redis中
            ResultEntity<String> saveCodeResultEntity =
                    redisRemoteService.setRedisKeyValueRemoteWithTimeout(key, code, 15, TimeUnit.MINUTES);

            //判断结果
            if (ResultEntity.SUCCESS == saveCodeResultEntity.getResult()) {
                return ResultEntity.successWithoutData();
            } else {
                return saveCodeResultEntity;
            }
        } else {
            return sendMessageResultEntity;
        }
    }





}
